#include "can.h"

volatile uint32_t gInterruptLine0Status;
volatile bool gServiceInt;
DL_MCAN_RxBufElement rxMsg;
DL_MCAN_TxBufElement txMsg;
DL_MCAN_RxFIFOStatus rxFS;
DL_MCAN_TxFIFOStatus txFS;

DL_MCAN_TxBufElement i_am_alive_msg;


bool can_rx_fifo_has_data(DL_MCAN_RX_FIFO_NUM fifoNum)
{
    rxFS.num = (uint32_t)fifoNum;
    DL_MCAN_getRxFIFOStatus(MCAN0_INST, &rxFS);

    return (rxFS.fillLvl > 0U);
}

uint32_t can_rx_fifo_fill_level(DL_MCAN_RX_FIFO_NUM fifoNum)
{
    rxFS.num = (uint32_t)fifoNum;
    DL_MCAN_getRxFIFOStatus(MCAN0_INST, &rxFS);

    return rxFS.fillLvl;
}

bool can_rx_fifo_pop(DL_MCAN_RX_FIFO_NUM fifoNum, DL_MCAN_RxBufElement *elem)
{
    uint32_t fifoValue;
    uint32_t getIdx;

    if (elem == NULL)
    {
        return false;
    }

    fifoValue = (uint32_t)fifoNum;
    rxFS.num = fifoValue;
    DL_MCAN_getRxFIFOStatus(MCAN0_INST, &rxFS);

    if (rxFS.fillLvl == 0U)
    {
        return false;
    }

    getIdx = rxFS.getIdx;
    DL_MCAN_readMsgRam(MCAN0_INST, DL_MCAN_MEM_TYPE_FIFO, 0U, fifoValue, elem);

    if (DL_MCAN_writeRxFIFOAck(MCAN0_INST, fifoValue, getIdx) != 0)
    {
        return false;
    }

    return true;
}

uint32_t can_tx_fifo_free_level(void)
{
    DL_MCAN_getTxFIFOQueStatus(MCAN0_INST, &txFS);

    return txFS.freeLvl;
}

bool can_tx_fifo_push(const DL_MCAN_TxBufElement *elem)
{
    uint32_t putIdx;

    if (elem == NULL)
    {
        return false;
    }

    DL_MCAN_getTxFIFOQueStatus(MCAN0_INST, &txFS);

    if (txFS.freeLvl == 0U)
    {
        return false;
    }

    putIdx = txFS.putIdx;

    DL_MCAN_writeMsgRam(MCAN0_INST, DL_MCAN_MEM_TYPE_FIFO, 0U, elem);
    DL_MCAN_TXBufAddReq(MCAN0_INST, putIdx);

    return true;
}

void can_build_standard_frame(
    DL_MCAN_TxBufElement *elem,
    uint16_t stdId,
    const uint8_t *payload,
    uint8_t length)
{
    uint8_t dlc;
    uint8_t i;

    if (elem == NULL)
    {
        return;
    }

    dlc = (length > 8U) ? 8U : length;

    elem->id = ((uint32_t)(stdId & 0x7FFU)) << 18U;
    elem->rtr = 0U;
    elem->xtd = ID_MODE_STANDARD;
    elem->esi = 0U;
    elem->dlc = dlc;
    elem->brs = 0U;
    elem->fdf = 0U;
    elem->efc = 1U;
    elem->mm = 0U;

    if (payload != NULL)
    {
        for (i = 0U; i < dlc; ++i)
        {
            elem->data[i] = payload[i];
        }
    }
    else
    {
        for (i = 0U; i < dlc; ++i)
        {
            elem->data[i] = 0U;
        }
    }

    for (; i < 8U; ++i)
    {
        elem->data[i] = 0U;
    }
}

void createTestFrame(void)
{
    static const uint8_t payload[8] = { 'I', 'a', 'm', 'a', 'l', 'i', 'v', 'e' };

    can_build_standard_frame(&i_am_alive_msg, 0x0123U, payload, (uint8_t)sizeof(payload));
    i_am_alive_msg.mm = 0xAAU;
}